﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using CodeGeneratorLibrary;
using Microsoft.Build.Evaluation;
using Templates.Bitrix.Admin.EditPage;
using Templates.Bitrix.Admin.ListPage;
using Templates.Bitrix.Database;
using Templates.Interfaces;

namespace Templates.Bitrix
{
	public class Rendering
	{
		public static void RenderListPage(List<string> messages)
		{
			List<ICodeFile> codeFile = new List<ICodeFile>();

			var sqlServer = new SqlServer(options.ConnectionString);
			Table table = sqlServer.LoadTable(options.TableToGenerate);


			var iViewEditCode = new AdminSapEventEdit_IView();
			iViewEditCode.BindData(table);

			var presenterEditCode = new AdminSapEventEdit_Presenter() { IView = iViewEditCode.ClassName, IViewNameSpace = iViewEditCode.Namespace };
			presenterEditCode.BindData(table);

			var baseClassEditCode = new SapEditBaseClass() { IViewNamespace = iViewEditCode.Namespace, PresenterNamespace = presenterEditCode.Namespace, IView = iViewEditCode.ClassName, Presenter = presenterEditCode.ClassName };
			baseClassEditCode.BindData(table);

			var aspxClassEditCode = new AdminSapEventEditPage_Behind() { FullBaseClass = string.Format("{0}.{1}", baseClassEditCode.Namespace, baseClassEditCode.ClassName) };
			aspxClassEditCode.BindData(table);

			var aspxPageEditCode = new AdminSapEventEditPage_View() { CodeFile = aspxClassEditCode.FileName, Inherits = string.Format("{0}.{1}", aspxClassEditCode.Namespace, aspxClassEditCode.ClassName) };
			aspxPageEditCode.BindData(table);

			var iViewListCode = new AdminSapEventList_IView();
			iViewListCode.BindData(table);

			var presenterListCode = new AdminSapEventList_Presenter() { IView = iViewListCode.ClassName, IViewNameSpace = iViewListCode.Namespace };
			presenterListCode.BindData(table);

			var baseClassListCode = new SapListBaseClass() { IViewNamespace = iViewListCode.Namespace, PresenterNamespace = presenterListCode.Namespace, IView = iViewListCode.ClassName, Presenter = presenterListCode.ClassName, EditPage = aspxPageEditCode.AspxPage };
			baseClassListCode.BindData(table);

			var aspxClassListCode = new AdminSapEventListPage_Behind() { FullBaseClass = string.Format("{0}.{1}", baseClassListCode.Namespace, baseClassListCode.ClassName), EditPage = aspxPageEditCode.AspxPage };
			aspxClassListCode.BindData(table);

			var aspxPageListCode = new AdminSapEventListPage_View() { CodeFile = aspxClassListCode.FileName, Inherits = string.Format("{0}.{1}", aspxClassListCode.Namespace, aspxClassListCode.ClassName), EditPage = aspxPageEditCode.AspxPage };
			aspxPageListCode.BindData(table);

			baseClassEditCode.ListPage = aspxPageListCode.AspxPage;
			baseClassEditCode.EditPage = aspxPageEditCode.AspxPage;


			codeFile.Add(iViewEditCode);
			codeFile.Add(presenterEditCode);
			codeFile.Add(aspxPageEditCode);
			codeFile.Add(aspxClassEditCode);
			codeFile.Add(baseClassEditCode);

			codeFile.Add(iViewListCode);
			codeFile.Add(presenterListCode);
			codeFile.Add(aspxPageListCode);
			codeFile.Add(aspxClassListCode);
			codeFile.Add(baseClassListCode);

			GenerateFile(messages, codeFile);
		}

		private static readonly Options options = Options.Factory;
		public static void Render(CodeFileType type, List<string> messages)
		{
			List<ICodeFile> codeFile = new List<ICodeFile>();

			var sqlServer = new SqlServer(options.ConnectionString);
			Table table = sqlServer.LoadTable(options.TableToGenerate);

			switch (type)
			{
				case CodeFileType.iview:
					var adminSapEventListIView = new AdminSapEventList_IView();
					codeFile.Add(adminSapEventListIView);
					adminSapEventListIView.BindData(table);
					break;
				case CodeFileType.presenter:
					var adminSapEventListPresenter = new AdminSapEventList_Presenter();
					codeFile.Add(adminSapEventListPresenter);
					adminSapEventListPresenter.BindData(table);
					break;
				case CodeFileType.view:
					RenderListPage(messages);
					return;
					break;
				case CodeFileType.entity:
					var entity = new SPComunication();
//					var entity = new Entity();
					codeFile.Add(entity);
					entity.BindData(table);
					break;
				case CodeFileType.entityDBFieldNames:
					var dbFieldNames = new DBFieldNames();
					codeFile.Add(dbFieldNames);
					dbFieldNames.BindData(table);
					break;
				case CodeFileType.script:
					var scripts = new Scripts();
					codeFile.Add(scripts);
					scripts.BindData(table);
					break;
				default:
					throw new ArgumentOutOfRangeException("type");
			}

			GenerateFile(messages, codeFile);
		}

		private static void GenerateFile(List<string> messages, List<ICodeFile> codeFiles)
		{

			foreach (var codeFile in codeFiles)
			{
				FileInfo projFileInfo = new FileInfo(codeFile.ProjFullName);
				DirectoryInfo directoryInfo;

				if (projFileInfo.Exists)
				{

					Project prj = ProjectCollection
						.GlobalProjectCollection
						.LoadedProjects
						.SingleOrDefault(x => x.FullPath.ToLower() == codeFile.ProjFullName.ToLower())
						?? new Project(codeFile.ProjFullName);


					if (!prj.GetItems(codeFile.ProjectFileType).Any(x => x.EvaluatedInclude == codeFile.ProjectFilePath))
					{
						prj.AddItem(codeFile.ProjectFileType, codeFile.ProjectFilePath);
						prj.Save();
						messages.Add(string.Format("<b>\"{0}\" add to project \"{1}\"</b>", codeFile.ProjectFilePath,
																			 codeFile.ProjFullName));
					}
					else
					{
						messages.Add(string.Format("\"{0}\" exist into project \"{1}\"", codeFile.ProjectFilePath, codeFile.ProjFullName));
					}
					ProjectCollection.GlobalProjectCollection.UnloadAllProjects();

					directoryInfo = projFileInfo.Directory;
				}
				else
				{
					messages.Add(string.Format("<span class=\"red\">Project \"{0}\" doesn't exist</span>", codeFile.ProjFullName));
					directoryInfo = new DirectoryInfo(codeFile.ProjFullName);
					if (!directoryInfo.Exists)
					{
						directoryInfo.Create();
						messages.Add(string.Format("<b>Directory \"{0}\" create</b>", directoryInfo));
					}
					else
					{
						messages.Add(string.Format("Directory \"{0}\" exist", directoryInfo));
					}
				}

				FileInfo generatedFile = new FileInfo(Path.Combine(directoryInfo.FullName, codeFile.ProjectFilePath));

				DirectoryInfo generatedDirectory = generatedFile.Directory;
				if (!generatedDirectory.Exists)
				{
					generatedDirectory.Create();
					messages.Add(string.Format("<b>Directory \"{0}\" create</b>", generatedDirectory.FullName));
				}
				else
				{
					messages.Add(string.Format("Directory \"{0}\" exist", generatedDirectory.FullName));
				}

				using (FileStream sw = new FileStream(generatedFile.FullName, FileMode.Create))
				{
					//var utf8 = new UTF8Encoding(false);
					//var bytes = utf8.GetBytes(codeFile.TransformText());
					var bytes = Encoding.UTF8.GetBytes(codeFile.TransformText());
					bytes = Encoding.UTF8.GetPreamble().Concat(bytes).ToArray();

					sw.Write(bytes, 0, bytes.Length);
					messages.Add(string.Format("<b>File \"{0}\" generated</b>", generatedFile.FullName));
				}
			}
		}
	}
}